package com.emotion.recognition.client;

import com.emotion.recognition.shared.MLPConfig;
import com.emotion.recognition.shared.Results;
import com.emotion.recognition.shared.SOMConfig;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class EmotionRecognition implements EntryPoint {

    // One panel for each section.
    UploadPanel uploadPanel = new UploadPanel();
    EditPanel editPanel;
    ResultsPanel resultsPanel;
    MLPConfigurator mlpConfigurator;
    SOMConfigurator somConfigurator;
    LoadingPanel loadingPanel;
    MLPConfig mlp;
    SOMConfig som;

    Panel currentPanel = Panel.UPLOAD;

    enum Panel {
        UPLOAD, EDIT, RESULTS, LOADING, CONFIGURE;
    }

    private final ProcessImageServiceAsync processImageService = GWT
            .create(ProcessImageService.class);

    /**
     * This is the entry point method.
     */
    @Override
    public void onModuleLoad() {
        Button continueButton = new Button("Continue");
        continueButton.getElement().setId("continueButton");
        continueButton.setStyleName("button");
        continueButton.addClickHandler(new ContinueClickHandler());

        // Add first panel to the root panel.
        RootPanel.get("panelContainer").add(uploadPanel);
        RootPanel.get("continueButtonContainer").add(continueButton);

        loadingPanel = new LoadingPanel();

        mlp = new MLPConfig();
        mlpConfigurator = new MLPConfigurator();

        som = new SOMConfig();
        somConfigurator = new SOMConfigurator();
    }

    private void showLoading(boolean show) {
        if (show) {
            RootPanel.get("panelContainer").add(loadingPanel);
        } else {
            loadingPanel.removeFromParent();
        }
    }

    class ContinueClickHandler implements ClickHandler {
        private String coordinates;

        @Override
        public void onClick(ClickEvent event) {
            showLoading(true);
            if (currentPanel == Panel.UPLOAD) {
                // Upload Panel;
                uploadPanel.formPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
                    @Override
                    public void onSubmitComplete(SubmitCompleteEvent event) {
                        String results = event.getResults();
                        if (!results.contains("500")) {
                            // Upload was a success.
                            currentPanel = Panel.EDIT;
                            showLoading(false);
                            System.out.println("DEBUG: " + results);

                            // Load new panel.
                            nextStep();
                            RootPanel.get("panelContainer").remove(0); // removes the upload panel
                            editPanel = new EditPanel(results);
                            RootPanel.get("panelContainer").add(editPanel);
                            editPanel.nextImage();
                            enableJCrop();
                        } else {
                            showLoading(false);
                            Window.alert("Upload Fail \n" + event.getResults());
                        }
                    }
                });
                uploadPanel.formPanel.submit();
            } else if (currentPanel == Panel.EDIT) {
                // Setup next image.
                int retval = editPanel.nextImage();
                if (retval > 0) {
                    showLoading(false);
                    enableJCrop();
                    if (retval == 2) {
                        // switch from training to testing
                        showLoading(false);
                        nextStep();
                    }
                } else if (retval == 0) {
                    coordinates = getCoordsFromJS();
                    System.out.println("DEBUG: " + coordinates);

                    currentPanel = Panel.CONFIGURE;
                    showLoading(false);
                    RootPanel.get("panelContainer").remove(0); // removes the edit panel
                    nextStep();
                    RootPanel.get("panelContainer").add(mlpConfigurator);
                    RootPanel.get("panelContainer").add(somConfigurator);
                }
            } else if (currentPanel == Panel.CONFIGURE) {
                mlp = mlpConfigurator.getValue();
                som = somConfigurator.getValue();

                // Finished, send information to server.
                processImageService.processImages(coordinates, editPanel.getTestingEmotions(), mlp,
                        som, new AsyncCallback<Results>() {

                            @Override
                            public void onSuccess(Results results) {
                                // Load new panel.
                                nextStep();
                                currentPanel = Panel.RESULTS;

                                // Remove loading panel.
                                showLoading(false);

                                // Load new panel.
                                resultsPanel = new ResultsPanel(results);
                                RootPanel.get("panelContainer").add(resultsPanel);
                            }

                            @Override
                            public void onFailure(Throwable caught) {
                                caught.printStackTrace();
                                Window.alert("Error on processing image");
                            }
                        });
            } else if (currentPanel == Panel.RESULTS) {
                // Just run the results again
                System.out.println("--- RUNNING RESULTS AGAIN ---");
                String coordinates = getCoordsFromJS();
                System.out.println("DEBUG: " + coordinates);

                mlp = mlpConfigurator.getValue();
                som = somConfigurator.getValue();

                // Finished, send information to server.
                processImageService.processImages(coordinates, editPanel.getTestingEmotions(), mlp,
                        som, new AsyncCallback<Results>() {

                            @Override
                            public void onSuccess(Results results) {
                                currentPanel = Panel.RESULTS;

                                // Remove loading panel.
                                showLoading(false);

                                // Load new panel.
                                resultsPanel = new ResultsPanel(results);
                                RootPanel.get("panelContainer").add(resultsPanel);
                            }

                            @Override
                            public void onFailure(Throwable caught) {
                                caught.printStackTrace();
                                Window.alert("Error on processing image");
                            }
                        });
            }
        }
    }

    native void enableJCrop() /*-{
		$wnd.initJCrop();
    }-*/;

    native void nextStep() /*-{
		$wnd.nextStep();
    }-*/;

    native String getCoordsFromJS() /*-{
		return $wnd.getCoords();
    }-*/;

}
